#pragma once

#include "Log.hpp"
#include "Socket.hpp"
#include "InetAddr.hpp"
#include "Common.hpp"

#include <memory>
#include <string>
#include <functional>
#include <sys/wait.h>

using namespace logModule;
using namespace SocketModule;

using ioservice_t = std::function<void(std::shared_ptr<Socket>, const InetAddr&)>;

class TcpServer
{
public:

    TcpServer(uint16_t port)
        :_isRunning(false)
        ,_port(port)
        ,_listenSocket(std::make_unique<TcpSocket>())
    {
        _listenSocket->buildTcpSocketMethod(_port);
    }

    void start(ioservice_t task)
    {
        _isRunning = true;
        while (true)
        {
            InetAddr client;

            auto sock = _listenSocket->accept(client);
            if (sock == nullptr)
            {
                continue;
            }
            LOG(LogLevel::DEBUG) << "accept success";
            
            int pid = fork();
            if (pid < 0)
            {
                LOG(LogLevel::WARNING) << "fork failure";
                exit(ExitCode::FORK_ERR);
            }
            else if (pid == 0)
            {
                LOG(LogLevel::DEBUG) << "fork success";

                _listenSocket->close(); // 子进程关闭关连的 listenSocket
                
                if (fork() > 0)
                {
                    exit(ExitCode::NORMAL);
                }

                task(sock, client); // 孙子进程执行
                sock->close();
                exit(ExitCode::NORMAL);               
            }
            else
            {
                sock->close();          // 父进程关闭连接成功的 sock
                ::waitpid(pid, nullptr, 0);
            }
        }
        _isRunning = false;
    }

private:

    uint16_t _port;
    std::unique_ptr<Socket> _listenSocket;
    bool _isRunning;
    
};

